﻿using CMS.Properties;
using CMS.REST;
using CMS.Util;
using Gma.QrCodeNet.Encoding;
using Gma.QrCodeNet.Encoding.Windows.Render;
using Newtonsoft.Json.Linq;
using System;
using System.Diagnostics;
using System.Drawing;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace CMS.Forms
{
    public partial class LoginDialog : Form
    {
        /// <summary>
        /// 表示当前是否是第一次登陆(在第一次登陆时,如果关闭,没有任何提示,直接关闭整个程序)
        /// </summary>
        private bool _IsFirstLogin = true;

        public string UserName
        {
            get
            {
                if (InvokeRequired)
                {
                    return (string)Invoke(new Func<string>(() => TB_UserName.Text));
                }
                else
                {
                    return TB_UserName.Text;
                }
            }
        }

        /// <summary>
        /// 当通过登陆成功时,此事件将被抛出
        /// </summary>
        public event EventHandler Logined;

        /// <summary>
        /// 缓存对象
        /// </summary>
        private static LoginDialog _Instance;

        /// <summary>
        /// 简单工厂
        /// </summary>
        /// <returns></returns>
        public static LoginDialog GetInstance()
        {
            if (_Instance == null || !_Instance.IsHandleCreated)
            {
                _Instance = new LoginDialog();
            }
            return _Instance;
        }

        /// <summary>
        /// 构造函数
        /// </summary>
        private LoginDialog()
        {
            InitializeComponent();
            TB_UserName.Text = Utils.PrivateProfile.ReadString("Root", "UserName", "");
            CB_RememberPwd.Checked = Utils.PrivateProfile.ReadString("Root", "RememberPwd", "").Equals("TRUE");
            if (CB_RememberPwd.Checked)
            {
                TB_Password.Text = Utils.FromBase64(Utils.PrivateProfile.ReadString("Root", "Password", ""));
            }
            PB_QrCode.Image = DrawString(new Bitmap(180, 180), "正在初始化");
        }

        /// <summary>
        /// 登陆按钮响应
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Bn_Login_Click(object sender, EventArgs e)
        {
            if (string.IsNullOrEmpty(TB_UserName.Text))
            {
                MessageBox.Show("用户名不能为空", "警告");
                return;
            }
            if (string.IsNullOrEmpty(TB_Password.Text))
            {
                MessageBox.Show("密码不能为空", "警告");
                return;
            }
            try
            {
                Bn_Login.Text = "登陆中";
                Application.DoEvents();
                JObject param = new JObject
                {
                    { "user_name", TB_UserName.Text },
                    { "password", Utils.MD5(TB_Password.Text) }
                };

                RESTResponse resp = RESTClient.HttpPost("apis/v1/login", param);
                if (resp.IsSuccess)
                {
                    Utils.PrivateProfile.WriteString("Root", "UserName", TB_UserName.Text);
                    if (CB_RememberPwd.Checked)
                    {
                        Utils.PrivateProfile.WriteString("Root", "RememberPwd", "TRUE");
                        Utils.PrivateProfile.WriteString("Root", "Password", Utils.ToBase64(TB_Password.Text));
                    }
                    else
                    {
                        Utils.PrivateProfile.WriteString("Root", "RememberPwd", "FALSE");
                        Utils.PrivateProfile.WriteString("Root", "Password", null);
                    }
                    RESTClient.SetAuthKey(resp.Data[0].ToObject<string>());
                    Permission.RefreshPermission();
                    Logined?.Invoke(this, EventArgs.Empty);
                    DialogResult = DialogResult.OK;
                    Hide();
                }
                else
                {
                    MessageBox.Show(resp.ErrMsg, "错误");
                }
            }
            finally
            {
                Bn_Login.Text = "管理员登陆";
            }
        }

        /// <summary>
        /// 当手动关闭对话框使,结束整个程序
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void LoginDialog_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (_IsFirstLogin)
            {
                if (e.CloseReason == CloseReason.UserClosing)
                {
                    Application.Exit();
                }
            }
            else
            {
                e.Cancel = true;
                if (MessageBox.Show(this, "如果退出,程序可能无法正常获取数据", "确认关闭登陆对话框吗?", MessageBoxButtons.YesNo) == DialogResult.Yes)
                {
                    Hide();
                }
            }
        }



        /// <summary>
        /// 使窗口就绪后立刻可以输入账号密码
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private async void LoginDialog_Activated(object sender, EventArgs e)
        {
            if (string.IsNullOrEmpty(TB_UserName.Text))
            {
                TB_UserName.Focus();
            }
            else
            {
                TB_Password.Focus();
            }
            if (await CheckBinding())
            {
                RefreshQrCode();
                T_Refresh.Start();
            }
            else
            {
                RefreshQrCode();
                T_Refresh.Stop();
            }
        }

        private bool _NoBinding = false;

        private async Task<bool> CheckBinding()
        {
            _NoBinding = await Task.Run(() =>
            {
                string bkey = Utils.GetComputerHash(RESTClient.GetServerTimeStamp());
                RESTResponse response = RESTClient.HttpPost("apis/v1/check_bkey", new JObject { { "bkey", bkey } });
                return !response.IsSuccess;
            });
            return _NoBinding;
        }

        #region 二维码部分
        private class SizeCalculation : ISizeCalculation
        {
            private readonly int _Size;

            public SizeCalculation(int size)
            {
                _Size = size;
            }

            public DrawingSize GetSize(int matrixWidth)
            {
                return new DrawingSize(_Size / matrixWidth, _Size, QuietZoneModules.Two);
            }
        }

        private QrEncoder _Encoder = new QrEncoder();
        private GraphicsRenderer _Renderer = new GraphicsRenderer(new SizeCalculation(180), Brushes.Black, Brushes.Transparent);
        private Font _QrCodeFont = new Font("微软雅黑", 16);
        private StringFormat _QrCodeFormat = new StringFormat() { Alignment = StringAlignment.Center, LineAlignment = StringAlignment.Center };

        /// <summary>
        /// 在指定的位图上绘制图片
        /// </summary>
        /// <param name="oldBitmap"></param>
        /// <returns></returns>
        private Image DrawQrCode(Image oldBitmap)
        {
            string bkey = Utils.GetComputerHash(RESTClient.GetServerTimeStamp());
            Debug.WriteLine("BKey:" + bkey, "INFO");
            QrCode qrCode = _Encoder.Encode(bkey);
            Graphics g = Graphics.FromImage(oldBitmap);
            g.DrawImage(Resource1.logo, new Rectangle(Point.Empty, oldBitmap.Size));
            _Renderer.Draw(g, qrCode.Matrix);
            g.Dispose();
            return oldBitmap;
        }

        /// <summary>
        /// 在指定的位图上绘制图片
        /// </summary>
        /// <param name="oldBitmap"></param>
        /// <param name="str"></param>
        /// <returns></returns>
        private Image DrawString(Image oldBitmap, string str)
        {
            Graphics g = Graphics.FromImage(oldBitmap);
            g.DrawImage(Resource1.logo, new Rectangle(Point.Empty, oldBitmap.Size));
            g.DrawString(str, _QrCodeFont, Brushes.Red, new Rectangle(Point.Empty, oldBitmap.Size), _QrCodeFormat);
            g.Dispose();
            return oldBitmap;
        }

        /// <summary>
        /// 用于防止RefreshQrCode()重入
        /// </summary>
        private bool _IsDrawing = false;

        /// <summary>
        /// 刷新验证码
        /// </summary>
        private async void RefreshQrCode()
        {
            if (_IsDrawing)
            {
                return;
            }

            await Task.Run(() =>
            {
                _IsDrawing = true;
                if (_NoBinding)
                {
                    PB_QrCode.Image = DrawString(PB_QrCode.Image, "值班地点未绑定");
                }
                else
                {
                    PB_QrCode.Image = DrawQrCode(PB_QrCode.Image);
                }

                _IsDrawing = false;
            });
        }

        private bool _IsManulRefresh = false;

        private async void PB_QrCode_Click(object sender, EventArgs e)
        {
            if (_IsManulRefresh)
            {
                return;
            }
            _IsManulRefresh = true;
            if (await CheckBinding())
            {
                RefreshQrCode();
                T_Refresh.Start();
            }
            else
            {
                RefreshQrCode();
                T_Refresh.Stop();
            }
            _IsManulRefresh = false;
        }

        private void T_Refresh_Tick(object sender, EventArgs e)
        {
            RefreshQrCode();
        }

        private void LoginDialog_Deactivate(object sender, EventArgs e)
        {
            T_Refresh.Stop();
        }
        #endregion
    }
}
